package SVN::TeamTools::Plugins::Hooks;

use warnings;
use strict;
use Carp;
use Error qw(:try);

use SVN::TeamTools::Store::Config;
use SVN::TeamTools::Store::Repo;
use SVN::TeamTools::Store::SvnIndex;
use SVN::TeamTools::Indexer;
#use SVN::TeamTools::DepFinder;
use SVN::TeamTools::CommitAnalyzer;

use HTML::Template;
use CGI;
use URI::Escape;
use Data::Dumper;
use File::Pid;
use Proc::Daemon;

my $pidfile = '/tmp/indexer.pid';
my $conf;
my $logger;
BEGIN { $conf = SVN::TeamTools::Store::Config->new(); $logger = $conf->{logger}; }

sub hasAction {
	shift;
	my %args	= @_;
	my $action	= $args{action};
	return ("|dsp.config|proc.hook.pre-commit|proc.hook.post-commit|" =~ /\|\Q$action\E\|/);
}

sub getTemplate {
	shift;
	my %args	= @_;
	my $action	= $args{action};
	my $cgi		= $args{cgi};
	if ($action =~ /dsp.config/) {
		return HTML::Template->new( filename => 'SVN/TeamTools/Plugins/tmpl/hooks-config.tmpl', path => @INC );
	}
}

sub procHook {
	shift;
	my %args	= @_;
	my $action	= $args{action};
	my $param	= $args{param};

	## Commit rules
	if ($action =~ /proc.hook.pre-commit/ and defined $conf->{config}->{commitrules} and defined $conf->{config}->{commitrules}->{rules}) {
		my $repopath	= $param->[0];
		my $txn		= $param->[1];

		my $repo = SVN::TeamTools::Store::Repo->new();
		my $look = $repo->getLook(txn=>$txn);

		foreach my $rule (@{$conf->{config}->{commitrules}->{rules}}) {
			my $reject;
			foreach my $regex (@{$rule->{regex}}) {
				my @tmptarget;
				if ($regex->{target}) {
					if ($regex->{target} eq 1) { @tmptarget = $look->added(); }
					if ($regex->{target} eq 2) { @tmptarget = $look->deleted(); }
					if ($regex->{target} eq 3) { @tmptarget = $look->updated(); }
					if ($regex->{target} eq 4) { @tmptarget = $look->copied_from(); }
					if ($regex->{target} eq 5) { @tmptarget = $look->copied_to(); }

					next if (! scalar @tmptarget);

					if (! defined ($reject)) {
						$reject=1;
					}

					my @target;
					for my $t (@tmptarget) {
						if ($regex->{objtype}) { # So, it's file
							push(@target, $look->cat($t));
						} else {
							push(@target, $t);
						}
					}

					$reject = $reject && ( (scalar(grep( m#$regex->{expression}#, @target))>0) ne ($regex->{operator} eq 1));
					$logger->debug("Commit rule: $regex->{expression}, target: ".Dumper(@target)." result: $reject");
						
				} else { # Commit message
					$reject=1;
					$reject = $reject && ( ($look->log_msg() =~ m#$regex->{expression}#) ne ($regex->{operator} eq 1));
					$logger->debug("Commit rule: $regex->{expression}, target (commit message): ".$look->log_msg()." result: $reject");
				}
				if (! $reject) {
					last;
				}
			}
			die "$rule->{notification}\n" if ($reject);
		}
	} elsif ($action =~ /proc.hook.post-commit/) {
		postCommitProcesses();
	}
}

sub postCommitProcesses {
	shift;

	$logger->debug ("Yep, post commit");

	# Background process for processing revisions
	

	my $checkpid = File::Pid->new({file => $pidfile});
	my $running=$checkpid->running();
	if (! $running) {
		$logger->info ("Starting indexing background processes");
		my $cmd= "perl -I /usr/local/teamtools/lib -MSVN::TeamTools::Plugins::Hooks -e'SVN::TeamTools::Plugins::Hooks::processrev' >>/var/log/teamtools/hookslog 2>&1";
		$logger->debug ($cmd);
		my $daemon = Proc::Daemon->new(
			work_dir     => '/tmp',
			exec_command => $cmd
		);
		my $pid=$daemon->Init();
		$checkpid->pid($pid);
		$checkpid->write();
		$logger->debug ("pid: $pid");
	} else {
		$logger->info("Daemon already running");
	}
#	exit;
}

sub processrev {
	my $pid = File::Pid->new({file => $pidfile});
	$pid->write();

	my $repo        = SVN::TeamTools::Store::Repo-> new();
	my $svnindex    = SVN::TeamTools::Store::SvnIndex->new (mode=>"r", create=>0);
#	my $depindex	= SVN::TeamTools::Store::DepIndex->new (mode=>"r", create=>0);
	my $stats       = SVN::TeamTools::Store::StatsDB->new (create=>0);

	my $svnrev;
	do {
		$svnrev = $repo->getSvnRev();
		my $indrev = $svnindex->getIndexRev();
#		my $deprev = $depindex->getIndexRev();
		my $starev = $stats->lastRev();
	
		if ($indrev < $svnrev) {
			SVN::TeamTools::Indexer->run();
		}
#		if ($deprev < $svnrev) {
#			SVN::TeamTools::DepFinder->run();
#		}
		if ($starev < $svnrev) {
			SVN::TeamTools::CommitAnalyzer->run();
		}
	} until ($svnrev == $repo->getSvnRev());
	$logger->info("Processing rev finished");
}
1;
